package com.xishu.controller;

import com.xishu.annotation.valid.MethodValidator;
import com.xishu.bo.MoveFoodTable;
import com.xishu.config.Constant;
import com.xishu.entity.User;
import com.xishu.entity.oplog.OrderOpLog;
import com.xishu.entity.order.Order;
import com.xishu.entity.order.OrderItem;
import com.xishu.entity.shop.FoodTable;
import com.xishu.entity.shop.Shop;
import com.xishu.exception.ResponseStatusException;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.service.order.base.OrderService;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;

@Api(description = "餐桌查询，开台")
@RestController
public class FoodTableController implements Tools {
    private static Logger logger = LoggerFactory.getLogger(FoodTableController.class);
    private CommonService commonService = CommonService.getInstance();
    private FoodTableService foodTableService = FoodTableService.getInstance();
    private OrderService orderService = OrderService.getInstance();

    @ApiOperation(value = "查询餐桌")
    @PutMapping(value = ("/food/table"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData search(@RequestBody FoodTable foodTable) throws Exception {
        return CommonService.getInstance().searchResponse(foodTable, (foodTableInDb) -> {
            //查询餐桌列表的时候，需要查询订单是否可以
            if (getBoolean(foodTable.getQueryCanCheckout())) {
                Order order = null;
                if (foodTableInDb.getRelateOrderId() != null) {
                    try {
                        Optional<Order> orderOptional = orderService.findOrderOptional(foodTableInDb.getShopId(), foodTableInDb.getRelateOrderId());
                        if (orderOptional.isPresent()) {
                            order = orderOptional.get();
                        } else {
                            logger.info("can not find the order");
                        }
                    } catch (ResponseStatusException e) {
                        logger.error("e", e);
                    }
                } else {
                    Optional<Order> orderOptional = orderService.findOrderByUniqueCode(foodTableInDb.getShopId(), foodTableInDb.getUniqueCode());
                    if (orderOptional.isPresent()) {
                        order = orderOptional.get();
                    } else {
                        logger.info("can not find the order");
                    }
                }

                boolean canCheckout = orderService.orderCanCheckout(order);
                foodTableInDb.setCanCheckout(canCheckout);
            }
        }, null, true);
    }

    @ApiOperation(value = "修改餐桌")
    @PutMapping(value = ("/food/table/modify"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData modify(@RequestBody FoodTable foodTable) throws Exception {
        return CommonService.getInstance().updateObject(foodTable, (f) -> {
            //如果有订单了，则需要更新对应订单的服务员
            if (isNotEmpty(f.getWaiterName()) || isNotEmpty(f.getWaiterId())) {
                try {
                    FoodTable foodTableInDb = commonService.findEntity(f.getId(), FoodTable.class);
                    Order order = orderService.findOrder(foodTableInDb.getShopId(), foodTableInDb.getRow(), foodTableInDb.getColumn(), foodTableInDb.getUniqueCode());

                    if (order != null) {
                        order.setWaiterId(f.getWaiterId());
                        order.setWaiterName(f.getWaiterName());

                        if (f.getWaiterId() != null && isEmpty(f.getWaiterName())) {
                            Long waiterId = f.getWaiterId();
                            Optional<User> userOptional = commonService.searchOneOptional(waiterId, User.class);
                            if (userOptional.isPresent()) {
                                order.setWaiterName(userOptional.get().getNickName());
                            }
                        }

                        commonService.save(order);
                    }

                    //同步餐桌配置
                    FoodTableService.getInstance().syncToOtherSceneFoodConfig(foodTableInDb);
                } catch (Exception e) {
                    logger.error("e");
                }
            }
        });
    }

    @ApiOperation(value = "拼桌或者开台餐桌")
    @PutMapping(value = ("/food/table/add"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShopId = true, checkShop = true)
    public ResponseData addOrTogether(@RequestBody FoodTable reqFoodTable) throws Exception {
        VerifyUtil.verify(() -> reqFoodTable.getShopId() != null);
        Shop shop = ShopService.getInstance().findShopById(reqFoodTable.getShopId());
        //餐厅一定要是营业状态
        VerifyUtil.verify(() -> getBoolean(shop.getBusinessStatus()), ResponseStatus.SHOP_CLOSED);
        FoodTable foodTable = foodTableService.addOrTogether(reqFoodTable, null);
        return commonService.createResponse(foodTable);
    }

    @ApiOperation(value = "删除餐桌，如果已经开台了不能删除")
    @DeleteMapping(value = ("/food/table"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData delete(@RequestBody FoodTable foodTable) throws Exception {
        VerifyUtil.verify(() -> foodTable.getId() != null);

        FoodTable foodTableInDb = null;

        if (foodTable.getId() != null) {
            foodTableInDb = commonService.searchOne(foodTable);

            if (foodTableInDb == null) {
                VerifyUtil.throwError(ResponseStatus.ORDER_DELETED);
            }

            if (getBoolean(foodTableInDb.getFlagDelete())) {
                VerifyUtil.throwError(ResponseStatus.ORDER_DELETED);
            }

            //如果是模板，则判断模板下面还有没有餐桌，有餐桌则不能删除
            if (getBoolean(foodTableInDb.getTemplate())) {
                logger.info("template table can not delete");
                List<FoodTable> openedFoodTableList = foodTableService.findFoodTable(foodTableInDb, false);
                VerifyUtil.verify(() -> isEmpty(openedFoodTableList), ResponseStatus.OPENED_FOOD_TABLE);
            }
        }

        logger.info("its not the fix table");

        if (foodTableInDb != null) {
            logger.info("will delete the food table {}", foodTableInDb);
            Integer status = getInt(foodTableInDb.getStatus());
            if (status == Constant.FOOD_TABLE_STATUS_PART_CASH) {
                VerifyUtil.throwError(ResponseStatus.ORDER_PART_PAID_CAN_NOT_DELETE);
            }
        } else {
            logger.info("will delete the food table {}", foodTable.getId());
        }

        final FoodTable finalFoodTableInDb = foodTableInDb;
        //真删
        return CommonService.getInstance().delete(foodTable, false, (FoodTable f) -> {
            //删除单个餐桌的时候，处理餐桌的状态
            if (finalFoodTableInDb != null && !getBoolean(finalFoodTableInDb.getTemplate())) {
                //查询模板，并处理
                try {
                    Long shopId = finalFoodTableInDb.getShopId();

                    if (!getBoolean(foodTable.notDeleteOrder)) {
                        //删除对应的订单
                        List<Order> orderList = foodTableService.findOrderByFoodTableKey(shopId, orderService.getFoodTableKey(finalFoodTableInDb));
                        logger.info("order list size is {}", orderList.size());
                        //只要没有付钱的订单都删除掉，已付钱的订单不删掉
                        orderList.stream().filter(p -> Constant.ORDER_UN_PAY_STATUS_LIST.contains(p.getStatus())).forEach(p -> {
                            try {
                                StockService.getInstance().deleteOrder(p);
                            } catch (Exception e) {
                                logger.error("e", e);
                            }
                            p.setFlagDelete(true);
                            commonService.directSave(p);
                        });

                        //添加删除的菜到报表
                        Optional<Order> orderOptional = orderList.stream().filter(p -> getBoolean(p.getParentOrder())).findFirst();

                        if (orderOptional.isPresent()) {
                            Order orderInDb = orderOptional.get();

                            //取消开台
                            OrderOpLogService opLogService = OrderOpLogService.getInstance();
                            OrderOpLog foodTableContent = opLogService.content(orderInDb, Constant.CANCEL_FOOD_TABLE);
                            opLogService.cancelFoodTable(orderInDb, foodTableContent);

                            logger.info("will add {} order item detail list to report ", orderInDb.getId());
                            List<OrderItem> orderItemList = getList(orderInDb.getOrderItemDetailList());
                            for (OrderItem orderItem : orderItemList) {
                                ReportService.getInstance().addDeleteOrderItem(orderItem.getId(), orderInDb);
                            }

                            //将落单审核清空掉
                            orderService.deleteAllAuditWithOrder(orderInDb);
                        }
                    }

                    foodTableService.dealTemplateFoodTable(finalFoodTableInDb);

                    List<FoodTable> sameConfigTableList = foodTableService.findSameConfigTable(finalFoodTableInDb);
                    for (FoodTable table : sameConfigTableList) {
                        logger.info("sync to delete {}", table.getId());
                        table.setFlagDelete(false);
                        table.setBeRequest(true);
                        commonService.delete(table);
                        logger.info("sync to deal template food table");
                        foodTableService.dealTemplateFoodTable(table);
                    }
                } catch (Exception e) {
                    logger.error("e", e);
                }
            }
        });
    }

    @ApiOperation(value = "移动餐桌")
    @PutMapping(value = ("/food/table/move"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true, checkShopId = true)
    public ResponseData move(@RequestBody MoveFoodTable moveFoodTable) throws Exception {
        //在新的餐桌那边去开台
        //把老的餐桌清空，删除
        Long shopId = moveFoodTable.getShopId();

        VerifyUtil.verify(() -> shopId != null);

        FoodTable des = moveFoodTable.getDes();
        VerifyUtil.verify(() -> des.getRow() != null && des.getColumn() != null);

        //找到源餐桌
        FoodTable srcFoodTableRequest = new FoodTable();
        srcFoodTableRequest.setId(moveFoodTable.getSrc().getId());
        FoodTable srcFoodTable = commonService.searchOne(srcFoodTableRequest);

        //不能为空
        VerifyUtil.verify(() -> srcFoodTable != null, ResponseStatus.ORDER_DELETED);
        Long sceneId = srcFoodTable.getSceneId();

        logger.info("src food table is  {}", srcFoodTable);
        //原始订单号
        Order srcOrder = orderService.findOrder(shopId, srcFoodTable.getUniqueCode());
        VerifyUtil.verify(() -> srcOrder != null, ResponseStatus.ORDER_NOT_EXIST);

        logger.info("src order is  {}", srcOrder);
        //校验原始订单的状态，只能是正在订餐的订单可以移动
        VerifyUtil.verify(() -> srcOrder.getStatus() == Constant.ORDER_STATUS_STARTING, ResponseStatus.ORDER_NOT_ORDERING_CAN_NOT_MOVE);

        //目标桌添加开台
        FoodTable addFoodTable = new FoodTable();
        addFoodTable.setShopId(shopId);
        addFoodTable.setSceneId(sceneId);
        addFoodTable.setRow(des.getRow());
        addFoodTable.setColumn(des.getColumn());
        addFoodTable.setDiners(srcFoodTable.getDiners());


        //开台并创建新的订单
        FoodTable desFoodTable = foodTableService.addOrTogether(addFoodTable, srcOrder);
        desFoodTable.setSendPrinter(srcFoodTable.getSendPrinter());
        commonService.save(desFoodTable);

        //如果不是固定餐厅的
        if (getInt(srcFoodTable.getUniqueCode()) != 0) {
            //拼台的移桌，那么重用以前的订单，修改坐标,以及标号
            moveRowAndColumn(srcOrder, desFoodTable);
            //原始餐桌删除
            logger.info("will delete add table");
            srcFoodTable.setNotDeleteOrder(true);
            delete(srcFoodTable);
            //修改餐桌状态
            foodTableService.dealOrderFoodTableStatus(srcOrder);
            return commonService.createResponse(srcOrder);
        } else {
            //直接新创建一个订单
            //查询目标餐桌订单，再返回给客户端
            Order newOrder = new Order();
            commonService.createObject(newOrder);
            //复制订单里面的数据
            BeanUtils.copyProperties(srcOrder, newOrder, "id", "createTime", "createDate", "entity", "flagDelete", "foodTableKey", "tableRow", "tableColumn", "uniqueCode", "code");
            newOrder.setFlagDelete(false);
            moveRowAndColumn(newOrder, desFoodTable);
            logger.info("new order is {}", newOrder);
            //固定餐桌，只删除订单就好了
            logger.info("will delete add fix table");
            delete(srcFoodTable);
            //修改餐桌状态
            foodTableService.dealOrderFoodTableStatus(newOrder);
            return commonService.createResponse(newOrder);
        }
    }

    /**
     * 移动横纵坐标
     *
     * @param srcOrder
     * @param desFoodTable
     * @throws Exception
     */
    private void moveRowAndColumn(Order srcOrder, FoodTable desFoodTable) throws Exception {
        srcOrder.setTableRow(desFoodTable.getRow());
        srcOrder.setTableColumn(desFoodTable.getColumn());
        srcOrder.setCode(desFoodTable.getCode());
        srcOrder.setShowNo(desFoodTable.getShowNo());
        srcOrder.setUniqueCode(desFoodTable.getUniqueCode());
        String foodTableKey = OrderService.getInstance().getFoodTableKey(srcOrder);
        srcOrder.setFoodTableKey(foodTableKey);
        commonService.save(srcOrder);
    }


}
